package com.linwl.weatherforecast;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.linwl.weatherforecast.builder.RecipientBuilder;
import com.linwl.weatherforecast.entity.RecipientEntity;
import com.linwl.weatherforecast.task.WorkTask;
import com.linwl.weatherforecast.utils.Common;
import com.linwl.weatherforecast.utils.TaskThreadFactory;
import com.linwl.weatherforecast.utils.YamlReader;
import lombok.extern.slf4j.Slf4j;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.*;

/**
 * @author ：linwl
 * @date ：Created in 2019/11/1 17:45
 * @description ：
 * @modified By：
 */
@Slf4j
public class WeartherApplication {

    private static final String ZERO_TIME = "00/00";
    private static final BlockingQueue<Runnable> TASK_QUEUE = new ArrayBlockingQueue<>(1000);

    public static void main(String[] args) throws Exception {
        log.info("天气预报服务启动中...");
        boolean exited = false;
        int poolSize =
                Integer.parseInt(
                        YamlReader.getInstance().getValueByPath("server.pool.pool-size").toString());
        int maxPoolSize =
                Integer.parseInt(
                        YamlReader.getInstance().getValueByPath("server.pool.max-pool-size").toString());
        int keepAliveTime =
                Integer.parseInt(
                        YamlReader.getInstance().getValueByPath("server.pool.keep-alive-time").toString());
        ExecutorService taskPool =
                new ThreadPoolExecutor(
                        poolSize,
                        maxPoolSize,
                        keepAliveTime,
                        TimeUnit.MILLISECONDS,
                        TASK_QUEUE,
                        new TaskThreadFactory(),
                        new ThreadPoolExecutor.AbortPolicy());
        List<Map<String, Object>> receiverList =
                (List<Map<String, Object>>) YamlReader.getInstance().getValueByPath("receivers");
        resetSendFalg(receiverList);
        log.info("天气预报接收人配置receiverList: {}", JSON.toJSONString(receiverList));
        log.info("天气预报服务启动完毕！");
        while (!exited) {
            try {
                String nowTime = DateUtil.format(DateUtil.date(), "HH/mm");
                if (Objects.equals(nowTime,ZERO_TIME)) {
                    resetSendFalg(receiverList);
                }
                for (Map<String, Object> receiver : receiverList) {
                    boolean sendFlag = (boolean) receiver.get("sendFalg");
                    String sendTime = String.valueOf(receiver.getOrDefault("sendTime", ""));
                    if (Objects.equals(nowTime,sendTime) && sendFlag) {
                        RecipientEntity recipientEntity =
                                new RecipientBuilder()
                                        .name(String.valueOf(receiver.getOrDefault("name", "")))
                                        .email(String.valueOf(receiver.getOrDefault("email", "")))
                                        .cityId(String.valueOf(receiver.getOrDefault("city-id", "")))
                                        .key(String.valueOf(receiver.getOrDefault("key", "")))
                                        .sendWeChat(Boolean.parseBoolean(String.valueOf(receiver.getOrDefault("wechat", "false"))))
                                        .build();
                        log.info("主线程发布进行对{}的发布任务!",recipientEntity.getName());
                        taskPool.submit(new WorkTask(recipientEntity));
                        receiver.put("sendFalg",false);
                        log.info("主线程完成对{}的任务发布!",recipientEntity.getName());
                    }
                }

            } catch (Exception e) {
                log.error(MessageFormat.format("天气预报服务发生异常:{0}!", e.getMessage()),e);
                exited = true;
                taskPool.shutdown();
            } finally {
                Thread.sleep(Common.getTime(1, "second"));
            }
        }
    }

    /**
     * 重置发送标志
     *
     * @param receiverList
     */
    public static void resetSendFalg(List<Map<String, Object>> receiverList){
        for (Map<String, Object> objectMap : receiverList) {
            objectMap.put("sendFalg",true);
        }
    }
}
